/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nanosn.coffeemaker.userinput;

import com.nanosn.coffeemaker.Project;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Handles the model classes created by the user.
 * @author selkhateeb
 */
public class Models
{
    /**
     * The default location of model classes.
     */
    private static String MODELS_DIRECTORY = "models";

    /**
     * Gets a list of maps that represent the user defined model classes.
     * Pre: The user has created model classes in the model directory.
     * Post: the list of maps has been generated and returned.
     * @param applicationName the name of the application.
     * @return the list of maps containing the user classes.
     * @throws java.lang.Exception
     */
    public static List<Map> getModels(String applicationName)
            throws Exception
    {
        List<Map> userEntities = new ArrayList<Map>();

        UserClasses userClasses = UserClasses.getInstance();
        userClasses.setUserApplicationDirectory(
                Project.PWD + applicationName +
                File.separator + MODELS_DIRECTORY + File.separator);

        List<String> cs = userClasses.getNameList();

        for (String className : cs)
        {
            userEntities.add(getModel(className, userClasses));
        }

        return userEntities;
    }


    /**
     * Creates a map containing the fields of the provided class.
     * Pre: the class exists.
     * Post: the map has been created and returned.
     * @param className
     * @param userClasses
     * @return a map containing the fields for the specified class.
     * @throws java.lang.Exception
     */
    @SuppressWarnings("unchecked")
    private static Map getModel(String className, UserClasses userClasses)
            throws Exception
    {
        System.out.println("Loading Class: " + className);

        //Load the class
        Class clazz = userClasses.getClassLoader().loadClass(className);


        List<String> classNamesList = userClasses.getNameList();

        Map map = new HashMap(2);
        List fields = new ArrayList();
        List relationFields = new ArrayList();
        List allFields = new ArrayList();


        map.put("name", clazz.getSimpleName());
        map.put("fields", fields);
        map.put("relationFields", relationFields);
        map.put("allFields", allFields);

        //Get all fields
        Field[] flds = clazz.getDeclaredFields();
        for (Field field : flds)
        {
            Map f = ExtractFieldSignature(field);

            if (classNamesList.contains(field.getType().getSimpleName()))
            {
                relationFields.add(f);
            }
            else
            {
                fields.add(f);
            }

            allFields.add(f);
        }
        return map;
    }

    /**
     * Creates a map containing the field properties.
     * Pre: the field exists.
     * Post: the map has been created and returned.
     * @param field
     * @return a map containing the field properties.
     */
    @SuppressWarnings("unchecked")
    private static Map ExtractFieldSignature(Field field)
    {
        //TODEV: handling annotations from user
        Map f = new HashMap();
        f.put("name", field.getName());
        f.put("type", field.getType().getSimpleName());

//        System.out.println("==============================================");
//        System.out.println("==============================================");
//        System.out.println("==============================================");
//        System.out.println("==============================================");
//        System.out.println("==============================================");
//        for (Annotation annotation : field.getDeclaredAnnotations())
//        {
//            System.out.println("Annotation: " + annotation.toString());
//            System.out.println("Annotation: " + annotation.annotationType().getSimpleName());
//        }
//
//
//        System.out.println("==============================================");
//        System.out.println("==============================================");
//        System.out.println("==============================================");
//        System.out.println("==============================================");
        return f;
    }
}
